﻿using RockBus.DataContracts;
using RockBus.Logging.Interfaces;
using RockBus.Subscription.Interfaces;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.ServiceModel;
using System.ServiceModel.Dispatcher;
using System.Xml;

namespace RockBus.Subscription.Evaluators
{
    public class MessageFilterFactory : IMessageFilterFactory
    {
        public MessageFilterFactory(ILogger logger)
        {
            this.Logger = logger;
        }

        private ILogger Logger { get; set; }

        public MessageFilter CreateMessageFilter(
            FilterInfo filterInfo,
            XmlNamespaceManager xmlNamespaces,
            IDictionary<string, FilterInfo> filters)
        {
            switch (filterInfo.FilterType)
            {
                case FilterTypeEnum.Action:
                    return new WildCardActionMessageFilter(filterInfo.FilterData);
                //return new ActionMessageFilter(new string[] { filterInfo.FilterData });

                case FilterTypeEnum.EndpointAddress:
                    return new EndpointAddressMessageFilter(new EndpointAddress(filterInfo.FilterData), false);

                case FilterTypeEnum.PrefixEndpointAddress:
                    return new PrefixEndpointAddressMessageFilter(new EndpointAddress(filterInfo.FilterData), false);

                case FilterTypeEnum.And:
                    {
                        MessageFilter filter1 = this.CreateMessageFilter(filters[filterInfo.Filter1Id], xmlNamespaces, filters);
                        MessageFilter filter2 = this.CreateMessageFilter(filters[filterInfo.Filter2Id], xmlNamespaces, filters);
                        return new StrictAndMessageFilter(filter1, filter2);
                    }
                case FilterTypeEnum.Custom:
                    return CreateCustomFilter(filterInfo.CustomTypeName, filterInfo.FilterData);

                case FilterTypeEnum.EndpointName:
                    return new EndpointNameMessageFilter(filterInfo.FilterData);

                case FilterTypeEnum.MatchAll:
                    return new MatchAllMessageFilter();

                case FilterTypeEnum.XPath:
                    return new XPathMessageFilter(filterInfo.FilterData, xmlNamespaces);

                case FilterTypeEnum.Topic:
                    this.Logger.LogDebug(MethodBase.GetCurrentMethod(), "Ignoring Filter with type Topic.");
                    return null;
                //return new TopicMessageFilter(filterInfo.FilterData, this.TopicEvaluator);
            }

            throw new ArgumentException("Invalid FilterType");
        }

        public MessageFilter CreateCustomFilter(string customType, string filterData)
        {
            if (string.IsNullOrEmpty(customType))
            {
                throw new ArgumentException("customType");
            }

            return (MessageFilter)Activator.CreateInstance(Type.GetType(customType, true), new object[] { filterData });
        }
    }
}